package protomysql

import (
	"encoding/binary"
	"encoding/hex"
	"fmt"
)

type MysqlStream struct {
	data  []byte
	point int
}

func NewMysqlStream(data []byte) *MysqlStream {
	return &MysqlStream{data: data}
}

func (s *MysqlStream) ReadNullTerminatedString() string {
	var res []byte
	var readOffset int
	for _, d := range s.data[s.point:] {
		readOffset++
		if d == 0 {
			break
		}
		res = append(res, d)
	}
	s.point += readOffset
	return string(res)
}

func (s *MysqlStream) ReadFixedLengthString(count int) string {
	return string(s.ReadBytes(count))
}

func (s *MysqlStream) ReadVariableLengthString() string {
	// TODO
	return ""
}

func (s *MysqlStream) ReadLengthEncodedString() string {
	return s.ReadFixedLengthString(s.ReadLengthEncodedInteger())
}

func (s *MysqlStream) ReadRestOfPacketString() string {
	return s.ReadFixedLengthString(len(s.data) - s.point)
}
func (s *MysqlStream) ReadFixedLengthInteger(byteCount int) int {
	val := []byte{0, 0, 0, 0}
	data := s.data[s.point : byteCount+s.point]
	for i, v := range data {
		val[i] = v
	}
	s.point += byteCount
	return int(binary.LittleEndian.Uint32(val))
}

func (s *MysqlStream) ReadBytes(count int) []byte {
	v := s.data[s.point : s.point+count]
	s.point += count
	return v
}

func (s *MysqlStream) Skip(count int) {
	s.point += count
}

// Greater or equal 	Lower than 	Stored as
//
// 0 251  1-byte  integer
//
// 251 216 0xFC + 2-byte integer
//
// 216 	224 0xFD + 3-byte integer
//
// 224 	264 0xFE + 8-byte integer
//
// If the first byte of a packet is a length-encoded integer and its byte value is 0xFE, you must check the length of the packet to verify that it has enough space for a 8-byte integer. If not, it may be an EOF_Packet instead.
func (s *MysqlStream) ReadLengthEncodedInteger() int {
	v := s.ReadFixedLengthInteger(1)
	if v < 0xfc {
		return v
	}
	if v < 0xfd {
		return s.ReadFixedLengthInteger(2)
	}
	if v < 0xfe {
		return s.ReadFixedLengthInteger(3)
	}
	if v == 0xfe {
		return s.ReadFixedLengthInteger(8)
	}
	panic(fmt.Sprintf("offset error %d", s.point))
}

func (s *MysqlStream) IsEof() bool {
	return s.point >= len(s.data)
}
func (s *MysqlStream) Dump() {
	println(hex.Dump(s.data))
}
